package edu.scau.tool.aspect;

import edu.scau.core.constants.AjaxResult;
import edu.scau.core.util.ServletUtils;
import edu.scau.system.service.TokenService;
import edu.scau.tool.annotation.RequestLog;
import edu.scau.tool.domain.Logs;
import edu.scau.tool.sevice.LogsService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * Controller接口请求日志切面
 */
@Aspect
@Component
@Slf4j
public class RequestLoggerAspect {
    @Autowired
    private Logs logs;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private LogsService logsService;
    /**
     * 定义切入点
     */
    @Pointcut(value = "@annotation(edu.scau.tool.annotation.RequestLog)")
    public void logPointcut(){
    }

    /**
     * 执行Before通知
     * 连接点：Before
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Before(value= "logPointcut()")
    public void doBeforeAdvice(JoinPoint joinPoint) throws Throwable {
        RequestLog requestLog = getAnnotationLog(joinPoint);
        if (requestLog == null) {
            return;
        }
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        String packageName = method.getDeclaringClass().getPackage().getName();
        String methodName = joinPoint.getSignature().getName();
        log.info("执行mapper方法：" + packageName+methodName);

        String requestUrl = ServletUtils.getRequest().getRequestURI();
        String requestMethod = ServletUtils.getRequest().getMethod();
        log.info("【mapper执行日志】"+"请求接口:" + requestUrl + ";请求方法类型为" + requestMethod);
        logs.setFuntionName(packageName+methodName);
        logs.setRequestUrl(requestUrl);
        logs.setFuntionType(requestMethod);
    }


    /**
     * 环绕通知记录耗时
     */
    @Around(value = "logPointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = null;
        try {
            result = pjp.proceed();
            return result;
        } finally {
            long end = System.currentTimeMillis();
            Method method = ((MethodSignature) pjp.getSignature()).getMethod();
            log.info("【mapper调用耗时】方法: {}，耗时: {} ms", method.getName(), end - start);
            logs.setDuration(end-start);
            logsService.insertLogs(logs);
        }
    }

    /**
     * 是否切入点方法上是否存在注解，如果存在就获取
     */
    private RequestLog getAnnotationLog(JoinPoint joinPoint) throws Exception {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null) {
            return method.getAnnotation(RequestLog.class);
        }
        return null;
    }
}
